package com.xbongbong.pro.rabbitmq.consumer;

import com.alibaba.fastjson.JSON;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.redis.RedisTimeConstant;
import com.xbongbong.pro.api.pojo.ApiWebHookRabbitMqDTO;
import com.xbongbong.pro.rabbitmq.binders.ApiWebHookConsumerBinder;
import com.xbongbong.pro.rabbitmq.constant.ApiWebHookBinderConstant;
import com.xbongbong.pro.rabbitmq.feign.WebHookFeignClient;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;

import javax.annotation.Resource;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

/**
 * webhook 消费者
 * @author 魏荣杰
 * @date 2019/10/10 16:28
 * @since v4.3.2.3
 * @version v4.3.2.3
 */
@EnableBinding(ApiWebHookConsumerBinder.class)
public class ApiWebHookListener {
    private static Logger LOG = LoggerFactory.getLogger(ApiWebHookListener.class);
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private WebHookFeignClient webHookFeignClient;

    public void callback(ApiWebHookRabbitMqDTO apiWebHookRabbitMqDTO, XbbRefTypeEnum xbbRefTypeEnum) {
        String corpid = apiWebHookRabbitMqDTO.getCorpid();
        Integer saasMark = apiWebHookRabbitMqDTO.getSaasMark();
        List<Long> dataIdList = apiWebHookRabbitMqDTO.getDataIdList();
        OperateTypeEnum operate = apiWebHookRabbitMqDTO.getOperate();
        String url = apiWebHookRabbitMqDTO.getUrl();
        Iterator<Long> it = dataIdList.iterator();
        while (it.hasNext()) {
            Long dataId = it.next();
            if (!checkWebHookConcurrentLock(corpid, xbbRefTypeEnum, saasMark, dataId, operate, url)) {
                it.remove();
                LOG.info("被锁了---dataId:" + dataId);
            }
        }
        if (dataIdList.isEmpty()) {
            return;
        }
        apiWebHookRabbitMqDTO.setDataIdList(dataIdList);
        webHookFeignClient.send(apiWebHookRabbitMqDTO);
    }

    /**
     * 获取api-webHook并发锁 若没有被占用则返回true并构建锁，若已被占用则返回false
     * 并发锁时间：默认三秒
     * @param corpid 公司id
     * @param xbbRefTypeEnum 业务类型
     * @param saasMark
     * @param dataId 数据id
     * @param operateTypeEnum 操作类型
     * @param url 回调地址
     * @return
     */
    public boolean checkWebHookConcurrentLock(String corpid, XbbRefTypeEnum xbbRefTypeEnum, Integer saasMark, Long dataId, OperateTypeEnum operateTypeEnum, String url) {
        String lockStr = corpid + "_" + xbbRefTypeEnum.getCode() + "_" + saasMark + "_" + dataId + "_" + operateTypeEnum.getCode() + "_" + url;
        if (Objects.equals(operateTypeEnum, OperateTypeEnum.NEW)) {
            // 新建回调无重复回调的可能，故加大过期时间
            return paasRedisHelper.checkConcurrentLock(RedisPrefixConstant.API_CALL_BACK, lockStr, 9, true);
        } else {
            return paasRedisHelper.checkConcurrentLock(RedisPrefixConstant.API_CALL_BACK, lockStr, RedisTimeConstant.MINI_DURATION, true);
        }
//        if (!Objects.equals(operateTypeEnum, OperateTypeEnum.EDIT)) {
//            if (Objects.equals(operateTypeEnum, OperateTypeEnum.NEW)) {
//                paasRedisHelper.checkConcurrentLock(RedisPrefixConstant.API_CALL_BACK_NEW, lockStr, RedisTimeConstant.MINI_DURATION, true);
//            }
//            return paasRedisHelper.checkConcurrentLock(RedisPrefixConstant.API_CALL_BACK, lockStr, RedisTimeConstant.MINI_DURATION, true);
//        } else {
//            /*
//             * 部分业务逻辑，新建的时候会自编辑，这种情况编辑不应该被回调
//             * 新建回调回调，短时间内有编辑回调，不触发
//             * 编辑操作回调，短时间内有编辑回调，不触发
//             */
//            boolean editFlag = paasRedisHelper.checkConcurrentLock(RedisPrefixConstant.API_CALL_BACK, lockStr, RedisTimeConstant.MINI_DURATION, true);
//            String newLockStr = corpid + "_" + xbbRefTypeEnum.getCode() + "_" + saasMark + "_" + dataId + "_" + OperateTypeEnum.NEW.getCode() + "_" + url;
//            boolean newFlag = paasRedisHelper.checkConcurrentLock(RedisPrefixConstant.API_CALL_BACK_NEW, newLockStr, RedisTimeConstant.MINI_DURATION, true);
//            return editFlag && newFlag;
//        }
    }

    @StreamListener(value = ApiWebHookBinderConstant.API_CUSTOMER_INPUT)
    public void apiCustomerInput(ApiWebHookRabbitMqDTO apiWebHookRabbitMqDTO) {
        LOG.info("apiCustomerInput Received: " + JSON.toJSONString(apiWebHookRabbitMqDTO));
        callback(apiWebHookRabbitMqDTO, XbbRefTypeEnum.CUSTOMER);
    }


    @StreamListener(value = ApiWebHookBinderConstant.API_CONTRACT_INPUT)
    public void apiContractInput(ApiWebHookRabbitMqDTO apiWebHookRabbitMqDTO) {
        LOG.info("apiContractInput Received: " + JSON.toJSONString(apiWebHookRabbitMqDTO));
        callback(apiWebHookRabbitMqDTO, XbbRefTypeEnum.CONTRACT);
    }


    @StreamListener(value = ApiWebHookBinderConstant.API_OPPORTUNITY_INPUT)
    public void apiOpportunityInput(ApiWebHookRabbitMqDTO apiWebHookRabbitMqDTO) {
        LOG.info("apiOpportunityInput Received: " + JSON.toJSONString(apiWebHookRabbitMqDTO));
        callback(apiWebHookRabbitMqDTO, XbbRefTypeEnum.SALES_OPPORTUNITY);
    }


    @StreamListener(value = ApiWebHookBinderConstant.API_CUSTOM_FORM_INPUT)
    public void apiCustomFormInput(ApiWebHookRabbitMqDTO apiWebHookRabbitMqDTO) {
        LOG.info("apiCustomFormInput Received: " + JSON.toJSONString(apiWebHookRabbitMqDTO));
        callback(apiWebHookRabbitMqDTO, XbbRefTypeEnum.SYSTEM);
    }

    @StreamListener(value = ApiWebHookBinderConstant.API_CLUE_INPUT)
    public void apiClueInput(ApiWebHookRabbitMqDTO apiWebHookRabbitMqDTO) {
        LOG.info("apiClueInput Received: " + JSON.toJSONString(apiWebHookRabbitMqDTO));
        callback(apiWebHookRabbitMqDTO, XbbRefTypeEnum.CLUE);
    }

    @StreamListener(value = ApiWebHookBinderConstant.API_CUSTOMER_COMMUNICATE_INPUT)
    public void apiCustomerCommunicateInput(ApiWebHookRabbitMqDTO apiWebHookRabbitMqDTO) {
        LOG.info("apiCustomerCommunicateInput Received: " + JSON.toJSONString(apiWebHookRabbitMqDTO));
        callback(apiWebHookRabbitMqDTO, XbbRefTypeEnum.CUSTOMER_COMMUNICATE);
    }

    @StreamListener(value = ApiWebHookBinderConstant.API_COMMON_INPUT)
    public void apiCommonInput(ApiWebHookRabbitMqDTO apiWebHookRabbitMqDTO) {
        LOG.info("apiCommonInput Received: " + JSON.toJSONString(apiWebHookRabbitMqDTO));
        callback(apiWebHookRabbitMqDTO, apiWebHookRabbitMqDTO.getXbbRefType());
    }


}
